<?php

namespace app\service\teach;

use app\exception\TokenInvalidException;
use QL\QueryList;
use think\facade\Cache;

/**
 * 强智教务系统
 * Class QiangzhiService
 * @package app\service\teach
 */
class QiangzhiService extends BaseService
{
    const QZ_TEACH_TOKEN_KEY = 'qz:teach:token:';  //强智教务系统存储TOKEN键  校园 + openid

    const LOGIN_URL = "xk/LoginToXk"; // 登录
    const MAIN_URL = "framework/xsMainV.htmlx"; // Main
    const PERSON_INFO_URL = "grsz/grsz_xggrxx.do"; // 获取个人信息

    const COURSE_INFO_URL = "xskb/xskb_list.do"; // 获取课表信息
    const COURSE_MAIN_URL = "framework/mainV_index_loadkb.htmlx"; // 获取主课表信息
    const COURSE_MAIN_NEW_URL = "framework/xsMainV_new.htmlx"; // 获取主课表new信息

    const SCORE_QUERY_URL = "kscj/cjcx_query"; // 获取成绩查询条件
    const SCORE_INFO_URL = "kscj/cjcx_list"; // 获取成绩信息

    const REVIEW_FIND_URL = "xspj/xspj_find.do"; //学生评价
    const REVIEW_LIST_URL = "xspj/xspj_list.do"; //评价信息
    const REVIEW_EDIT_URL = "xspj/xspj_edit.do"; //编辑评价
    const REVIEW_SAVE_URL = "xspj/xspj_save.do"; //保存评价

    const REVIEW_DATA = [
        "pj0601id_3" => [
            "E3937A8B24AB478F85128B8C304CA05B" => "优秀",
            "7E8CAB403A084008A41537939584A90C" => "良好",
            "ED0403BFE25A4FB9BFA0D79D627BCE19" => "合格",
            "3A5C5C80E381450F9D8040CB211153F5" => "不合格",
        ],
        "pj0601id_4" => [
            "7CC9C17CF6C4445AB5C428EC825FC33E" => "优秀",
            "2A10BF376F4348E08A9ACC62ED0F8D21" => "良好",
            "A56A68628F8A488599E22E6CDEC1A503" => "合格",
            "1B51C9BC08B0463396C8959FBB012D7B" => "不合格",
        ],
        "pj0601id_2" => [
            "A76C6B1ABDF343759AA5ECCE647E9EA5" => "优秀",
            "B0FA4F8CE1F84154B705BF5254A1DF62" => "良好",
            "81FDAE4662264C8FB3BD97DB93989D62" => "合格",
            "7280099270634162A904DF37B1780DE9" => "不合格",
        ],
        "pj0601id_5" => [
            "8804CA7D97A64373AC5C14C03C22EEEF" => "优秀",
            "D7B636D9FAB14F0CAB171161B51853F6" => "良好",
            "787C4E0CF7E545E2B89FD73BE11D5915" => "合格",
            "290BAE14201D40A4A3067678E978D41D" => "不合格",
        ],
    ];

    /*
     * 获取token信息
     */
    public function getToken() {
        $token = Cache::get($this->getTokenKey());
        $data = json_decode($token, true);
        if ($data) {
            return $data['token'];
        }

        // 没有token提示登录
        throw new TokenInvalidException();
    }

    /*
     * 清理token信息
     */
    public function clearToken() {
        Cache::delete($this->getTokenKey());
    }

    public function getTokenKey() {
        return self::QZ_TEACH_TOKEN_KEY . getUserTokenKey();
    }

    /*
     * 获取token信息
     */
    public function login($number, $password) {
        $params = [
            'loginMethod'   => "LoginToXk",
            'userAccount'  => $number,
            'userPassword' => $password,
            'encoded' => encodeInp($number) . "%%%" . encodeInp($password),
        ];

        $loginRes = $this->call(self::LOGIN_URL, $params, "POST", ['allow_redirects' => false], false);
        if ($loginRes->getStatusCode() != 302) {
            $loginHtml = $loginRes->getBody()->getContents();
            $errMsg = QueryList::html($loginHtml)->find("#showMsg")->text();
            return ['status' => -1, 'msg' => $errMsg];
        } else {
            $data = [
                "token" => implode(",", $loginRes->getHeader("Set-Cookie")),
                "time"  => time(),
            ];
            Cache::set($this->getTokenKey(), json_encode($data), 3600);
            return ['status' => 0, 'msg' => '成功'];
        }
    }

    /*
     * 获取主框架信息, 可作为维活机制
     */
    public function getMainInfo() {
        $this->call(self::MAIN_URL, [], "GET", ['headers' => [
            'Cookie' => getToken()
        ]]);
    }

    /*
     * 获取个人信息
     */
    public function getPersonInfo() {
        $personInfoRes = $this->call(self::PERSON_INFO_URL, [], "GET", [
            'headers' => [
                'Cookie' => $this->getToken()
            ]
        ]);
        $account = QueryList::html($personInfoRes)->find("#account")->val();
        $name = QueryList::html($personInfoRes)->find("#realName")->val();
        $mobile = QueryList::html($personInfoRes)->find("#xsdh")->val();
        $email = QueryList::html($personInfoRes)->find("#xsdzxx")->val();

        return [
            "number" => $account,
            "name" => $name,
            "mobile" => $mobile,
            "email" => $email,
        ];
    }

    /*
     * 获取课表信息
     */
    public function getCourseInfo($week = '', $xqxn = '') {
        if (!$week) {
            $courseMainNewRes = $this->call(self::COURSE_MAIN_NEW_URL, ["t1" => 1], "GET", [
                'headers' => [
                    'Cookie' => $this->getToken()
                ]
            ]);
            $week = QueryList::html($courseMainNewRes)->find(".layui-this .msg")->text();
        }

        $params = [
            "zc" => $week,
            "xnxq01id" => $xqxn,
        ];

        $courseInfoRes = $this->call(self::COURSE_INFO_URL, $params, "GET", [
            'headers' => [
                'Cookie' => $this->getToken()
            ]
        ]);

        if (!$xqxn) {
            $xqxn = QueryList::html($courseInfoRes)->find("#xnxq01id option:selected")->text();
        }
        // 周次
        $weekData = QueryList::html($courseInfoRes)->find("#zc option")->text();
        $weekArr = explode("\n", $weekData);
        // 学年学期
        $xqxmData = QueryList::html($courseInfoRes)->find("#xnxq01id option")->text();
        $xqxmArr = explode("\n", $xqxmData);

        $table = QueryList::html($courseInfoRes)->find('#timetable');
        // 采集表头
        $tableHeader = $table->find('tr:eq(0)')->find('th')->texts();
        $tableHeader = $tableHeader->toArray();
        if ($tableHeader) {
            unset($tableHeader[0]);
        }

        // 采集表的每行内容
        $courseData = [];
        for ($i = 0; $i <= 7; $i++) {
            for ($j = 1; $j <= 10; $j++) {
                $table->find('tr:eq('.$j.')>td:eq('.$i.')')->map(function($row) use (&$courseData, $i, $j){
                    $kbcontent = $row->find('.kbcontent')->html();
                    $teacher = QueryList::html($kbcontent)->find("font[title='教师']")->text();
                    $week = QueryList::html($kbcontent)->find("font[title='周次(节次)']")->text();
                    $floor = QueryList::html($kbcontent)->find("font[title='教学楼']")->text();
                    $room = QueryList::html($kbcontent)->find("font[title='教室']")->text();
                    $kbList = explode("<br>", $row->find('.kbcontent')->html());
                    $courseData[$i][$j] = count($kbList) > 2 ? [$kbList[0] , $teacher, $week, $room, $floor] : [];
                })->all();
            }
        }

        return [
            'week_list' => $weekArr,
            'xqxm_list' => $xqxmArr,
            'fields' => $tableHeader,
            'values' => $courseData,
            'default_week' => $week,
            'default_xqxm' => $xqxn,
        ];
    }

    /*
     * 获取成绩查询条件
     */
    public function getScoreQuery() {
        $scoreQueryRes = $this->call(self::SCORE_QUERY_URL, [], "GET", [
            'headers' => [
                'Cookie' => $this->getToken(),
            ]
        ]);

        // 默认学期
        $defaultXq = QueryList::html($scoreQueryRes)->find("#kksj option:selected")->text();
        $defaultXqArr = explode("\n", $defaultXq);
        // 学期
        $xqData = QueryList::html($scoreQueryRes)->find("#kksj option")->text();
        $xqArr = explode("\n", $xqData);
        // 课程性质
        $typeData = QueryList::html($scoreQueryRes)->find("#kcxz option")->text();
        $typeArr = explode("\n", $typeData);
        // 显示方式
        $showData = QueryList::html($scoreQueryRes)->find("#xsfs option")->text();
        $showArr = explode("\n", $showData);

        return [
            "xq_list" => $xqArr,
            'type_list' => $typeArr,
            'show_list' => $showArr,
            'default_xq' => end($defaultXqArr),
        ];
    }

    /*
     * 获取成绩信息
     */
    public function getScoreInfo($xq, $type = '', $name = '', $show = "all") {
        $params = [
            "kksj" => $xq,
            "kcxz" => $type,
            "kcmc" => $name,
            "xsfs" => $show,
        ];
        $scoreInfoRes = $this->call(self::SCORE_INFO_URL, $params, "POST", [
            'headers' => [
                'Cookie' => $this->getToken(),
            ]
        ]);

        $table = QueryList::html($scoreInfoRes)->find('#dataList');
        // 采集表头
        $tableHeader = $table->find('tr:eq(0)')->find('th')->texts()->all();
        // 采集表的每行内容
        $tableRows = $table->find('tr:gt(0)')->map(function($row){
            return $row->find('td')->texts()->all();
        })->all();
        foreach ($tableRows as $k => $v) {
            if (count($v) < 5) {
                unset($tableRows[$k]);
            } else {
                array_unshift($tableRows[$k], false);
            }
        }

        return [
            'fields' => $tableHeader,
            'values' => $tableRows,
        ];
    }

    /*
     * 获取学生评价
     */
    public function getReviewFind() {
        $reviewFindRes = $this->call(self::REVIEW_FIND_URL, [], "GET", [
            'headers' => [
                'Cookie' => $this->getToken()
            ]
        ]);

        $table = QueryList::html($reviewFindRes)->find('#Form1');
        // 采集表头
        $tableHeader = $table->find('tr:eq(0)')->find('th')->texts()->all();
        // 采集表的每行内容
        $tableRows = $table->find('tr:gt(0)')->map(function($row){
            return $row->find('td')->texts()->all();
        })->all();
        foreach ($tableRows as $k => $v) {
            if (count($v) < 2) {
                unset($tableRows[$k]);
            }
        }
        // 采集表的最后一行内容
        $tableHrefRows = $table->find('tr:gt(0)')->map(function($row){
            return $row->find('td:last a')->attr("href");
        })->all();
        foreach ($tableHrefRows as $k => $v) {
            $arr = explode("?", $v);
            if (count($arr) > 1) {
                $tableHrefRows[$k] = $arr[1];
            }
        }
        return [
            'fields' => $tableHeader,
            'values' => $tableRows,
            'urls' => $tableHrefRows,
        ];
    }

    /*
     * 获取评价信息
     */
    public function getReviewList($url) {
        $reviewInfoRes = $this->call(self::REVIEW_LIST_URL, $url, "GET", [
            'headers' => [
                'Cookie' => $this->getToken()
            ]
        ]);

        $table = QueryList::html($reviewInfoRes)->find('#dataList');
        // 采集表头
        $tableHeader = $table->find('tr:eq(0)')->find('th')->texts()->all();
        // 采集表的每行内容
        $tableRows = $table->find('tr:gt(0)')->map(function($row){
            return $row->find('td')->texts()->all();
        })->all();
        // 采集表的最后一行内容
        $tableHrefRows = $table->find('tr:gt(0)')->map(function($row){
            return $row->find('td:last a')->attr("href");
        })->all();
        foreach ($tableHrefRows as $k => $v) {
            $arr = explode("?", $v);
            if (count($arr) > 1) {
                $tableHrefRows[$k] = $arr[1];
            }
        }
        return [
            'fields' => $tableHeader,
            'values' => $tableRows,
            'urls' => $tableHrefRows,
        ];
    }

    /*
     * 评价详情
     */
    public function getReviewDetail($url) {
        $reviewEditRes = $this->call(self::REVIEW_EDIT_URL, $url, "GET", [
            'headers' => [
                'Cookie' => $this->getToken()
            ]
        ]);

        $review_name = QueryList::html($reviewEditRes)->find(".Nsb_r_list_thb")->text();
        $pj0601id_3 = QueryList::html($reviewEditRes)->find("input[name=pj0601id_3]:checked")->val();
        $pj0601id_4 = QueryList::html($reviewEditRes)->find("input[name=pj0601id_4]:checked")->val();
        $pj0601id_2 = QueryList::html($reviewEditRes)->find("input[name=pj0601id_2]:checked")->val();
        $pj0601id_5 = QueryList::html($reviewEditRes)->find("input[name=pj0601id_5]:checked")->val();
        $jynr = QueryList::html($reviewEditRes)->find("#jynr")->val();

        return [
            'review_name' => explode("\r\n", $review_name)[0] ?? '',
            "pj0601id_3" => $pj0601id_3 ? (self::REVIEW_DATA["pj0601id_3"][$pj0601id_3] ?? '') : '',
            "pj0601id_4" => $pj0601id_4 ? (self::REVIEW_DATA["pj0601id_4"][$pj0601id_4] ?? '') : '',
            "pj0601id_2" => $pj0601id_3 ? (self::REVIEW_DATA["pj0601id_2"][$pj0601id_2] ?? '') : '',
            "pj0601id_5" => $pj0601id_5 ? (self::REVIEW_DATA["pj0601id_5"][$pj0601id_5] ?? '') : '',
            "jynr" => $jynr,
        ];
    }

    /*
     * 编辑评价信息
     */
    public function getReviewEdit($url, $issumbit, $pj0601id_3, $pj0601id_4, $pj0601id_2, $pj0601id_5, $jynr) {
        $reviewEditRes = $this->call(self::REVIEW_EDIT_URL, $url, "GET", [
            'headers' => [
                'Cookie' => $this->getToken()
            ]
        ]);

        $table = QueryList::html($reviewEditRes)->find('#Form1');
        $params = [];
        $table->find('input')->map(function($input) use (&$params){
           if (!in_array($input->name, ["qx", "tj", "bc"]) && $input->name != "pj06xh") {
               $params[$input->name] = $input->value;
           }
        });
        $params["issubmit"] = $issumbit;
        $params["pj0601id_3"] = array_flip(self::REVIEW_DATA["pj0601id_3"])[$pj0601id_3] ?? '';
        $params["pj0601id_4"] = array_flip(self::REVIEW_DATA["pj0601id_4"])[$pj0601id_4] ?? '';
        $params["pj0601id_2"] = array_flip(self::REVIEW_DATA["pj0601id_2"])[$pj0601id_2] ?? '';
        $params["pj0601id_5"] = array_flip(self::REVIEW_DATA["pj0601id_5"])[$pj0601id_5] ?? '';
        $params["jynr"] = $jynr;
        $rawData = http_build_query($params) . "&pj06xh=3&pj06xh=4&pj06xh=2&pj06xh=5";

        $reviewSaveRes = $this->call(self::REVIEW_SAVE_URL, [], "POST", [
            'headers' => [
                'Cookie' => $this->getToken()
            ],
            'query' => $rawData
        ]);

        preg_match("/alert\('(.*)'\);/", $reviewSaveRes, $msgText);
        if (isset($msgText[1])) {
            return ['msg' => $msgText[1]];
        } else {
            return ['msg' => '保存错误'];
        }
    }
}

// 模拟js的charCodeAt()方法
function charCodeAt($str, $index)
{
    $char = mb_substr($str, $index, 1, 'UTF-8');
    if ($char!=='' && mb_check_encoding($char, 'UTF-8'))
    {
        $ret = mb_convert_encoding($char, 'UTF-32BE', 'UTF-8');
        return hexdec(bin2hex($ret));
    } else {
        return null;
    }
}

// 加密方法
function encodeInp($input)
{
    $keyStr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
    $output = '';
    $i = 0;
    do {
        $chr1 = charCodeAt($input, $i++);
        $chr2 = charCodeAt($input, $i++);
        $chr3 = charCodeAt($input, $i++);
        $enc1 = $chr1 >> 2;
        $enc2 = (($chr1 & 3) << 4) | ($chr2 >> 4);
        $enc3 = (($chr2 & 15) << 2) | ($chr3 >> 6);
        $enc4 = $chr3 & 63;
        if ($chr2 === null) {
            $enc3 = $enc4 = 64;
        } else if ($chr3 == null) {
            $enc4 = 64;
        }
        $output = $output . $keyStr[$enc1] . $keyStr[$enc2] . $keyStr[$enc3] . $keyStr[$enc4];
    } while ($i < strlen($input));
    return $output;
}
